from django.conf import settings
from django.db.models import Avg, Sum, Count, Max, Min, Q, F
from django.forms.models import model_to_dict

import django_filters
from django_filters.rest_framework import DjangoFilterBackend, FilterSet
from rest_framework.filters import SearchFilter

from rest_framework import serializers
from rest_framework.serializers import *
from rest_framework.validators import UniqueValidator, UniqueTogetherValidator  # 验证器

# from allinpay import apidev as PAY
from mysqldb.models import *
from mysqldb import redis as REDIS


class NoneSerializer(serializers.Serializer):
    """无序列化"""

    class Meta:
        fields = "__all__"


# 用户注册
class AllinpayUserCreateSerializer(serializers.ModelSerializer):
    """注册用户"""

    phone = RegexField(
        r"^1[23456789]\d{9}$",
        max_length=255,
        required=True,
        help_text="移动电话号码，后台登录账号(必填)",
        validators=[UniqueValidator(queryset=AllinpayUserList.objects.all())],
    )
    email = EmailField(
        max_length=255,
        required=False,
        help_text="电子邮箱(选填)",
        validators=[UniqueValidator(queryset=AllinpayUserList.objects.all())],
    )
    name = CharField(max_length=255, required=False, help_text="真实姓名(选填)")
    openid = CharField(
        max_length=255,
        required=False,
        help_text="微信openid(选填)",
        validators=[UniqueValidator(queryset=AllinpayUserList.objects.all())],
    )
    password = CharField(max_length=255, required=True, help_text="用户密码(密文)")
    creattime = HiddenField(default=timezone.now)
    group = HiddenField(default=1)
    status = HiddenField(default=1)  # 启用、禁用 (管理员控制)
    is_active = HiddenField(default=1)  # 激活
    is_super = HiddenField(default=0)  # 超级账户
    is_authenticated = HiddenField(default=0)  # 登录后台

    class Meta:
        model = AllinpayUserList
        fields = (
            "name",
            "phone",
            "email",
            "openid",
            "password",
            "creattime",
            "group",
            "status",
            "is_active",
            "is_super",
            "is_authenticated",
        )


class AllinpayUserLoginSerializer(serializers.Serializer):
    """登录用户"""

    username = CharField(max_length=255, required=True, help_text="用户名(手机、邮箱或openid)")
    password = CharField(max_length=255, required=True, help_text="用户密码")
    act = ChoiceField(
        ["PASSWORD", "SEMS", "EMAIL"], required=True, help_text="验证方式(密码、短信、邮件)"
    )

    class Meta:
        fields = "__all__"


class AllinpayUserActivationSerializer(serializers.Serializer):
    """激活用户"""

    username = CharField(max_length=255, required=True, help_text="用户名(手机、邮箱或openid)")
    password = CharField(max_length=255, required=True, help_text="验证码")

    class Meta:
        fields = "__all__"


class AllinpayUserListSerializer(serializers.ModelSerializer):
    """用户列表"""

    basename = CharField(max_length=255, required=False, help_text="昵称")
    name = CharField(max_length=255, required=False, help_text="真实姓名")
    phone = RegexField(
        r"^1[23456789]\d{9}$",
        max_length=255,
        required=True,
        help_text="移动电话号码，后台登录账号",
        validators=[UniqueValidator(queryset=AllinpayUserList.objects.all())],
    )
    email = EmailField(
        max_length=255,
        required=False,
        help_text="电子邮箱",
        validators=[UniqueValidator(queryset=AllinpayUserList.objects.all())],
    )
    openid = CharField(
        max_length=255,
        required=False,
        help_text="微信openid",
        validators=[UniqueValidator(queryset=AllinpayUserList.objects.all())],
    )
    idcode = RegexField(
        r"^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$",
        max_length=255,
        required=True,
        help_text="身份证号码",
        validators=[UniqueValidator(queryset=AllinpayUserList.objects.all())],
    )
    avatar = CharField(
        required=False,
        help_text="用户头像",
    )
    creattime = ReadOnlyField()
    last_login = ReadOnlyField()
    group = ReadOnlyField()
    status = ReadOnlyField()
    is_active = ReadOnlyField()
    is_authenticated = ReadOnlyField()
    is_super = ReadOnlyField()
    bind = SerializerMethodField()
    grouped = SerializerMethodField()

    class Meta:
        model = AllinpayUserList
        fields = (
            "id",
            "basename",
            "name",
            "phone",
            "email",
            "openid",
            "idcode",
            "avatar",
            "creattime",
            "last_login",
            "group",
            "status",
            "is_active",
            "is_authenticated",
            "is_super",
            "bind",
            "grouped",
        )

    def get_bind(self, attr):
        if not attr.is_authenticated:
            return []

        perm = AllinpayAuthGroupPermissions.objects.filter(
            group_id=attr.group
        ).values_list("permission_id", flat=True)
        rn = AllinpayAuthViews.objects.filter(id__in=perm).values("id", "info", "act")

        return list(rn)

    def get_grouped(self, attr):
        if not attr.is_authenticated:
            return []
        try:
            sess = AllinpayAuthGroup.objects.get(id=attr.group)
        except BaseException as err:
            return ""
        return sess.name


class AllinpayUserStatusSerializer(serializers.ModelSerializer):
    """用户状态"""

    id = IntegerField(help_text="用户ID")
    status = IntegerField(min_value=0, max_value=1, default=0, help_text="用户状态")

    class Meta:
        model = AllinpayUserList
        fields = ("id", "status")

    def validate_id(self, attr):
        try:
            AllinpayUserList.objects.get(id=attr)
        except BaseException as err:
            raise serializers.ValidationError("对象不存在")
        return attr


class AllinpayUserGroupSerializer(serializers.ModelSerializer):
    """用户角色"""

    id = IntegerField(help_text="用户ID")
    group = IntegerField(min_value=1, default=1, help_text="用户角色")

    class Meta:
        model = AllinpayUserList
        fields = ("id", "group")

    def validate_id(self, attr):
        try:
            AllinpayUserList.objects.get(id=attr)
        except BaseException as err:
            raise serializers.ValidationError("用户对象不存在")
        return attr

    def validate_group(self, attr):
        try:
            AllinpayAuthGroup.objects.get(id=attr, pid=0)
        except BaseException as err:
            raise serializers.ValidationError("角色对象不存在")
        return attr


class AllinpayUserActiveSerializer(serializers.ModelSerializer):
    """用户激活"""

    id = IntegerField(help_text="用户ID")
    is_active = IntegerField(min_value=0, max_value=1, default=0, help_text="用户激活")

    class Meta:
        model = AllinpayUserList
        fields = ("id", "is_active")

    def validate_id(self, attr):
        try:
            AllinpayUserList.objects.get(id=attr)
        except BaseException as err:
            raise serializers.ValidationError("对象不存在")
        return attr


class AllinpayUserBackstSerializer(serializers.ModelSerializer):
    """用户后台"""

    id = IntegerField(help_text="用户ID")
    is_authenticated = IntegerField(
        min_value=0, max_value=1, default=0, help_text="用户后台登录"
    )

    class Meta:
        model = AllinpayUserList
        fields = ("id", "is_authenticated")

    def validate_id(self, attr):
        try:
            AllinpayUserList.objects.get(id=attr)
        except BaseException as err:
            raise serializers.ValidationError("对象不存在")
        return attr


class AllinpayUserSuperSerializer(serializers.ModelSerializer):
    """用户超级"""

    id = IntegerField(help_text="用户ID")
    is_super = IntegerField(min_value=0, max_value=1, default=0, help_text="用户超级")

    class Meta:
        model = AllinpayUserList
        fields = ("id", "is_super")

    def validate_id(self, attr):
        try:
            AllinpayUserList.objects.get(id=attr)
        except BaseException as err:
            raise serializers.ValidationError("对象不存在")
        return attr


class AllinpayAuthGroupSerializer(serializers.ModelSerializer):
    """用户角色表"""

    pid = HiddenField(default=0, help_text="场所ID")
    name = CharField(help_text="角色名称")
    bind = SerializerMethodField()

    class Meta:
        model = AllinpayAuthGroup
        fields = "__all__"
        validators = [
            UniqueTogetherValidator(
                queryset=AllinpayAuthGroup.objects.all(), fields=["name", "pid"]
            ),
        ]

    def validate_pid(self, attr):
        try:
            AllinpayPlaceList.objects.get(id=attr)
        except BaseException as err:
            if not attr == 0:
                raise serializers.ValidationError("场所对象不存在")
        return attr

    def get_bind(self, attr):
        try:
            sess = AllinpayPlaceList.objects.get(id=attr.pid)
            return sess.name
        except BaseException as err:
            return "后台"


class AllinpayAuthGroupPermissionsSerializer(serializers.ModelSerializer):
    """角色权限"""

    id = IntegerField(label="ID", read_only=True)
    group_id = IntegerField(required=True, help_text="角色ID")
    permission_id = IntegerField(required=True, help_text="权限ID")

    class Meta:
        model = AllinpayAuthGroupPermissions
        fields = "__all__"
        validators = [
            UniqueTogetherValidator(
                queryset=AllinpayAuthGroupPermissions.objects.all(),
                fields=("group_id", "permission_id"),
            )
        ]

    def validate_group_id(self, attr):
        if attr == 1:
            raise serializers.ValidationError("默认角色不能赋予任何权限")
        try:
            AllinpayAuthGroup.objects.get(id=attr)
        except BaseException as err:
            raise serializers.ValidationError("角色对象不存在")
        return attr

    def validate_permission_id(self, attr):
        try:
            AllinpayAuthViews.objects.get(id=attr)
        except BaseException as err:
            raise serializers.ValidationError("权限对象不存在")
        return attr


class AllinpayAuthViewsSerializer(serializers.ModelSerializer):
    """视图列表"""

    id = IntegerField(label="ID", read_only=True)
    name = CharField(required=False, help_text="视图名称")
    info = CharField(required=False, help_text="视图功能")
    act = CharField(required=False, help_text="操作方法")

    class Meta:
        model = AllinpayAuthViews
        fields = "__all__"
        validators = [
            UniqueTogetherValidator(
                queryset=AllinpayAuthViews.objects.all(), fields=("name", "act")
            )
        ]


class AllinpayAuthUserPermissionSerializer(serializers.ModelSerializer):
    """用户权限"""

    id = IntegerField(label="ID", read_only=True)
    uid = IntegerField(required=True, help_text="用户ID")
    pid = IntegerField(required=True, help_text="场所ID")
    permid = IntegerField(required=True, help_text="权限ID")

    class Meta:
        model = AllinpayAuthUserPermission
        fields = "__all__"
        validators = [
            UniqueTogetherValidator(
                queryset=AllinpayAuthUserPermission.objects.all(),
                fields=("uid", "permid", "pid"),
            )
        ]

    def validate_uid(self, attr):
        try:
            AllinpayUserList.objects.get(id=attr)
        except BaseException as err:
            raise serializers.ValidationError("用户对象不存在")
        return attr

    def validate_pid(self, attr):
        try:
            AllinpayPlaceList.objects.get(id=attr)
        except BaseException as err:
            if not attr == 0:
                raise serializers.ValidationError("场所对象不存在")
        return attr

    def validate(self, attrs):
        attrs = dict(attrs)
        role = AllinpayUserplaceList.objects.filter(
            uid=attrs["uid"], pid=attrs["pid"]
        ).values_list("group", flat=True)
        if not attrs["permid"] in self.hasPerms(list(role)):
            raise serializers.ValidationError({"permid": "该权限不支持"})
        return attrs

    def hasPerms(self, role):
        """返回去重后的合法权限列表"""
        sess = []
        sess += list(
            AllinpayAuthGroupPermissions.objects.filter(group_id__in=role).values_list(
                "permission_id", flat=True
            )
        )
        return sorted(list(set(sess)), key=sess.index)


class AllinpayPasswordSerializer(serializers.ModelSerializer):
    """修改密码"""

    id = IntegerField(help_text="用户ID")
    password = CharField(required=True, help_text="视图名称")

    class Meta:
        model = AllinpayUserList
        fields = ("id", "password")

    def validate_id(self, attr):
        try:
            AllinpayUserList.objects.get(id=attr)
        except BaseException as err:
            raise serializers.ValidationError("对象不存在")
        return attr


class AllinpayUserBankSerializer(serializers.ModelSerializer):
    """用户银行卡"""

    id = IntegerField(label="ID", read_only=True)
    userid = IntegerField(
        help_text="用户ID",
        validators=[UniqueValidator(queryset=AllinpayUserBank.objects.all())],
    )
    status = IntegerField(min_value=0, max_value=1, default=1, help_text="状态")
    bankname = CharField(help_text="银行名称")
    bankuser = CharField(help_text="户名")
    bankcard = CharField(help_text="卡号")
    cbccode = CharField(help_text="联行号")

    class Meta:
        model = AllinpayUserBank
        fields = "__all__"

    def validate_userid(self, attr):
        try:
            AllinpayUserList.objects.get(id=attr)
        except BaseException as err:
            raise serializers.ValidationError("用户对象不存在")
        return attr


class AllinpayUserobjectListSerializer(serializers.ModelSerializer):
    """用户对象列表"""

    id = IntegerField(label="ID", read_only=True)
    uid = IntegerField(allow_null=True, help_text="用户ID")
    pid = IntegerField(allow_null=True, help_text="场所ID")
    user = SerializerMethodField()
    place = SerializerMethodField()

    class Meta:
        model = AllinpayUserobjectList
        fields = "__all__"
        validators = [
            UniqueTogetherValidator(
                queryset=AllinpayUserobjectList.objects.all(), fields=("uid", "pid")
            )
        ]

    def get_user(self, attrs):
        try:
            sess = AllinpayUserList.objects.get(id=attrs.uid)
        except BaseException as err:
            return {}
        else:
            return model_to_dict(sess)

    def get_place(self, attrs):
        try:
            sess = AllinpayPlaceList.objects.get(id=attrs.pid)
        except BaseException as err:
            return {}
        else:
            return model_to_dict(sess)


# print(repr(AllinpayUserobjectListSerializer()))
